package base.core.mybatis;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.springframework.util.StringUtils;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Mybatis数组,符串互转
 * <p>
 * MappedJdbcTypes 数据库中的数据类型 MappedTypes java中的的数据类型
 *
 * @author xuzihui
 * @date 2019-11-20
 */
@MappedTypes(value = {Integer[].class})
public class ArrayIntegerTypeHandler extends BaseTypeHandler<Integer[]> {

	private static final String splitCharset = ",";

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, Integer[] objects, JdbcType jdbcType) throws SQLException {
		String str = arrayToString(objects);
		ps.setString(i, str);
	}

	@Override
	public Integer[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
		String str = rs.getString(columnName);
		return stringToArray(str);
	}

	@Override
	public Integer[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		String str = rs.getString(columnIndex);
		return stringToArray(str);
	}

	@Override
	public Integer[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		String str = cs.getString(columnIndex);
		return stringToArray(str);
	}

	// --- private methods ---

	/**
	 * Integer数组转String
	 * 注：使用提前设定好的分隔符分割数组的每一项
	 */
	private static String arrayToString(Integer[] array) {
		if (array == null || array.length == 0) {
			return null;
		}
		String collect = Arrays.stream(array).map(integer -> integer.toString()).collect(Collectors.joining(splitCharset,splitCharset,splitCharset));
		return collect;
	}

	/**
	 * 从String转Integer数组
	 * 注：String是用分隔符分割的，使用String.split方法可以分解为数组
	 */
	private static Integer[] stringToArray(String str) {
		if (!StringUtils.hasText(str)) {
			return null;
		}
		String[] split = str.split(splitCharset);
		List<Integer> collect = Arrays.stream(split).filter(s-> StringUtils.hasText(s)).map(s -> stringToInteger(s)).filter(integer -> integer != null).collect(Collectors.toList());
		return collect.toArray(new Integer[0]);
	}


	private static Integer stringToInteger(String str){
		try {
			return Integer.valueOf(str);
		}catch (Exception e){
		}

		return null;
	}
}
